﻿//-----------------------------------------------------------------------
//  This file is part of the Microsoft Code Samples.
// 
//  Copyright (C) Microsoft Corporation.  All rights reserved.
// 
//  This source code is intended only as a supplement to Microsoft
//  Development Tools and/or on-line documentation.  See these other
//  materials for detailed information regarding Microsoft code samples.
// 
//  THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//  PARTICULAR PURPOSE.
//-----------------------------------------------------------------------

namespace Microsoft.Samples.ReportingServices
{
    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.ReportingServices.ReportRendering;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Collections.Specialized;

    /// <summary>
    /// The main class of our custom report item design-time component
    /// The report processor first calls the Process method, and then
    /// reads the RenderItem property to get the rendered report item.
    /// </summary>
    public class PolygonsCCustomReportItem : ICustomReportItem
    {
        private CustomReportItem customReportItem;
        private Microsoft.ReportingServices.ReportRendering.Image polygonImage;
        private Microsoft.ReportingServices.ReportRendering.ImageMapAreasCollection imageMap;

        // holds the custom report item property values defined using the Report Designer
        // and stored in the report definition
        public CustomReportItem CustomItem
        {
            get
            {
                return this.customReportItem;
            }

            set
            {
                this.customReportItem = value;
            }
        }

        // returns the rendered custom report item
        public ReportItem RenderItem
        {
            get
            {
                if (this.polygonImage == null)
                {
                    this.Process();
                }

                return this.polygonImage;
            }
        }

        // this is not implemented for SQL Server 2005 and should always return null
        public Action Action
        {
            get
            {
                return null;
            }
        }

        // access the data saved with the custom report item in the design environment and
        // creates the custom report item which is returned via the RenderItem property
        public ChangeType Process()
        {
            int dpi = 96;
            int imageWidth = (int)(this.customReportItem.Width.ToInches() * dpi);
            int imageHeight = (int)(this.customReportItem.Height.ToInches() * dpi);
            Bitmap image = new Bitmap(imageWidth, imageHeight);
            Graphics graphics = Graphics.FromImage(image);
            Color backgroundColor = ((ReportColor)this.customReportItem.Style["BackgroundColor"]).ToColor();
            if (backgroundColor == Color.Transparent)
            {
                backgroundColor = Color.White;
            }

            graphics.Clear(backgroundColor);
            int maxX = (int)LookupCustomProperty(this.customReportItem.CustomProperties, "poly:MaxX", 100);
            int maxY = (int)LookupCustomProperty(this.customReportItem.CustomProperties, "poly:MaxY", 100);
            int minX = (int)LookupCustomProperty(this.customReportItem.CustomProperties, "poly:MinX", 0);
            int minY = (int)LookupCustomProperty(this.customReportItem.CustomProperties, "poly:MinY", 0);
            float scaleX = imageWidth / (float)(maxX - minX);
            float scaleY = imageHeight / (float)(maxY - minY);
            string proportional = (string)LookupCustomProperty(this.customReportItem.CustomProperties, "poly:Proportional", bool.FalseString);

            if ((string)proportional == bool.TrueString)
            {
                if (scaleX > scaleY)
                {
                    scaleX = scaleY;
                }
                else
                {
                    scaleY = scaleX;
                }
            }

            string transString = (string)LookupCustomProperty(this.customReportItem.CustomProperties, "poly:Translucent", "Opaque");
            int translucency = 255;

            switch (transString)
            {
                case "Opaque": 
                    translucency = 255; 
                    break;

                case "Translucent": 
                    translucency = 128; 
                    break;

                case "Transparent": 
                    translucency = 32; 
                    break;
            }

            DataMemberCollection shapes = this.customReportItem.CustomData.DataRowGroupings[0];

            this.imageMap = new ImageMapAreasCollection();

            int row = 0;

            for (int i = 0; i < shapes.Count; i++)
            {
                DataMember shape = shapes[i];
                string colorname = (string)LookupCustomProperty(shape.CustomProperties, "poly:Color", "Black");
                ReportColor rptColor = new ReportColor(colorname);
                Color color = Color.FromArgb(translucency, rptColor.ToColor());
                Brush brush = new SolidBrush(color);
                DataMemberCollection points = shape.Children[0];
                string hyperlink = (string)LookupCustomProperty(shape.CustomProperties, "poly:Hyperlink", "");
                ImageMapArea imageMapArea = new ImageMapArea();
                float[] coordinates = new float[points.Count * 2];
                Point[] drawpoints;
                drawpoints = new Point[points.Count];
                for (int j = 0; j < points.Count; j++)
                {
                    DataCell point = this.customReportItem.CustomData.DataCells[row, 0];
                    int x = 0;
                    int y = 0;
                    for (int val = 0; val < point.DataValues.Count; val++)
                    {
                        string name = point.DataValues[val].Name;
                        object value = point.DataValues[val].Value;
                        int intvalue = 0;
                        if (value.GetType() == typeof(int))
                        {
                            intvalue = (int)value;
                        }
                        else if (value.GetType() == typeof(double))
                        {
                            intvalue = (int)((double)value);
                        }

                        if (name == "X")
                        {
                            x = (int)((intvalue - minX) * scaleX);
                        }
                        else if (name == "Y")
                        {
                            y = (int)((intvalue - minY) * scaleY);
                        }
                    }

                    drawpoints[j] = new Point(x, y);
                    coordinates[j * 2] = 100 * x / imageWidth;
                    coordinates[j * 2 + 1] = 100 * y / imageHeight;
                    row = row + 1;
                }

                if (!string.IsNullOrEmpty(hyperlink))
                {
                    imageMapArea.SetCoordinates(ImageMapArea.ImageMapAreaShape.Polygon, coordinates);
                    Action action = new Action();
                    action.SetHyperlinkAction(hyperlink);
                    if (imageMapArea.ActionInfo == null)
                    {
                        imageMapArea.ActionInfo = new ActionInfo();
                    }

                    if (imageMapArea.ActionInfo.Actions == null)
                    {
                        imageMapArea.ActionInfo.Actions = new ActionCollection();
                    }

                    imageMapArea.ActionInfo.Actions.Add(action);
                    this.imageMap.Add(imageMapArea);
                }

                graphics.FillPolygon(brush, drawpoints);
            }

            // copy the rendered image to a ReportRendering Image type
            // to be returned via the RenderItem property
            this.polygonImage = new Microsoft.ReportingServices.ReportRendering.Image(this.customReportItem.Name, this.customReportItem.ID);

            System.IO.MemoryStream stream = new System.IO.MemoryStream();
            image.Save(stream, ImageFormat.Bmp);

            this.polygonImage.ImageData = new byte[(int)stream.Length];
            stream.Seek(0, System.IO.SeekOrigin.Begin);
            stream.Read(this.polygonImage.ImageData, 0, (int)stream.Length);
            this.polygonImage.MIMEType = "image/bmp";

            if (this.imageMap.Count > 0)
            {
                this.polygonImage.ImageMap = this.imageMap;
            }

            stream.Close();

            // this should always return ChangeType.None for SQL Server 2005
            return ChangeType.None;
        }

        // utility method to return custom report item properties from the collection
        private static object LookupCustomProperty(CustomPropertyCollection properties, string name, object defaultValue)
        {
            if (properties == null)
            {
                return defaultValue;
            }

            CustomProperty property = properties[name];
            if (property == null)
            {
                return defaultValue;
            }

            if ((property.Value.GetType() == typeof(String)) && string.IsNullOrEmpty((string)property.Value))
            {
                return defaultValue;
            }

            return property.Value;
        }
    }
}
